package com.larry.tinyweb.core.annotation;

import com.larry.tinyweb.core.ActionInvoke;
import com.larry.tinyweb.core.InvokeEntity;
import com.larry.tinyweb.core.RequestEntity;
import com.larry.tinyweb.core.annotation.AnnotationContainer;
import com.larry.tinyweb.core.annotation.RM;
import com.larry.tinyweb.core.annotation.Unit;
import com.larry.tinyweb.core.log.Logger;
import com.larry.tinyweb.core.log.LoggerFactory;
import com.larry.tinyweb.plugin.proxy.TX;
import com.larry.tinyweb.util.proxy.ProxyUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by larry on 16/12/3.
 * @author larry
 * RM 注解路由管理类
 */
public class RmAnnotationHandler extends AnnotationHandler {
    public static Logger logger = LoggerFactory.getLogger(RmAnnotationHandler.class);

    private Map<String, ActionInvoke> rmMap;
    public RmAnnotationHandler() {
        rmMap = new HashMap<>();
    }

    /**
     * 初始化RM注解
     */
    @Override
    public void resolve() {
        try {
            List<Unit> units = AnnotationContainer.getContainer().typeOfAnnotation(RM.class);
            for (Unit unit : units) {
                resolveRM(unit);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析class的RM
     */
    private void resolveRM(Unit unit) throws IllegalAccessException, InstantiationException {
        Class cls = unit.getClasz();
        // 解析类头的请求路径
        String actionURL = null;
        if (cls.isAnnotationPresent(RM.class)) {
            RM rm = (RM) cls.getAnnotation(RM.class);
            actionURL = rm.value();
        } else {
            return;
        }

        // 解析方法头注解
        for (Method m : cls.getMethods()) {
            if (m.isAnnotationPresent(RM.class)) {

                RM rm = m.getAnnotation(RM.class);
                String methodURL = rm.value();
                String key = actionURL + methodURL;
                if (key.endsWith("/")) key = key.substring(0, key.length() - 1);
                key.replaceAll("//", "/");


                InvokeEntity invokeEntity = new InvokeEntity(key, unit, m);

                // 判断是否有事务注解
                if (m.isAnnotationPresent(TX.class)) {
                    // 事务动态代理
                    ActionInvoke proxyTxObj = (ActionInvoke) ProxyUtil.
                            proxyForTransaction(ActionInvoke.class, invokeEntity);
                    rmMap.put(key, proxyTxObj);
                } else {
                    rmMap.put(key, invokeEntity);
                }
                System.out.println("= = = > map : " + key);
            }
        }
    }


    /**
     * 执行请求调用
     * @param requestEntity
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public void map(RequestEntity requestEntity) throws Exception {
//        String key = "/" + requestEntity.getRouterName() + "/" + requestEntity.getMethodName();
        String key = requestEntity.getRouterName() + requestEntity.getMethodName();
        logger.debug(key);
        try {
            rmMap.get(key).invoke(requestEntity);
        } catch (Exception e) {
            e.printStackTrace();
            requestEntity.go404();
        }
    }
}
